package gagak.framework.web.paramresovler;

import gagak.framework.web.paramresovler.converter.HandlerMethodReturnValueHandler;
import com.g5.framework.web.annonation.Nullable;
import com.g5.framework.web.param.MethodParameter;
import com.g5.framework.web.support.NativeWebRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/*
 * @program: ce
 * @description: 返回参数解析，使用组合模式，递归执行
 * @author: houhong
 * @create: 2022-12-01 00:46
 */
public class HandlerMethodReturnValueHandlerComposite implements HandlerMethodReturnValueHandler {

    // 日志
    private static final Logger logger = LoggerFactory.getLogger(HandlerMethodReturnValueHandlerComposite.class);

    private List<HandlerMethodReturnValueHandler> returnValueHandlers = new ArrayList<HandlerMethodReturnValueHandler>();

    public List<HandlerMethodReturnValueHandler> getHandlers() {
        return Collections.unmodifiableList(this.returnValueHandlers);
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {

        return getReturnValueHandler(returnType) != null;
    }


    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType, NativeWebRequest webRequest) throws Exception {


        HandlerMethodReturnValueHandler handler = selectHandler(returnType);
        if (handler == null) {
            throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
        }
        handler.handleReturnValue(returnValue, returnType, webRequest);
    }

    private HandlerMethodReturnValueHandler selectHandler(MethodParameter returnType) {

        for (HandlerMethodReturnValueHandler returnValueHandler : returnValueHandlers) {
            if (returnValueHandler.supportsReturnType(returnType)) {
                return returnValueHandler;
            }
        }
        return null;
    }


    //递归查找一直满足的
    private HandlerMethodReturnValueHandler getReturnValueHandler(MethodParameter returnType) {

        for (HandlerMethodReturnValueHandler returnValueHandler : this.returnValueHandlers) {
            if (returnValueHandler.supportsReturnType(returnType)) {
                return returnValueHandler;
            }
        }
        return null;
    }

    public HandlerMethodReturnValueHandlerComposite addHandler(HandlerMethodReturnValueHandler handler) {
        this.returnValueHandlers.add(handler);
        return this;
    }

    /*
     * Add the given {@link HandlerMethodReturnValueHandler}s.
     */
    public HandlerMethodReturnValueHandlerComposite addHandlers(
            @Nullable List<? extends HandlerMethodReturnValueHandler> handlers) {

        if (handlers != null) {
            this.returnValueHandlers.addAll(handlers);
        }
        return this;
    }
}